package com.sl.crawler.robot.clientPool;

import com.sl.crawler.common.enums.crawler.EmRunState;
import com.sl.crawler.robot.request.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by shiling on 2017/6/9.
 */
public abstract class BaseClientPool<T> {
    private final static Logger LOG = LoggerFactory.getLogger(BaseClientPool.class);
    private AtomicInteger runState = new AtomicInteger(EmRunState.RUNNING.getValue());

    private static Integer CAPACITY = 1;

    /**
     * 创建T
     */
    private List<T> clientList = Collections.synchronizedList(new ArrayList<T>());

    /**
     * 可用的T队列
     */
    private BlockingDeque<T> clientQueue = new LinkedBlockingDeque<>();


    public abstract void closeOne(T client);

    public abstract T createClient();

    public abstract String getUrl(T client, Request request) throws Exception;

    /**
     * 不使用代理
     *
     * @return
     */
    public T getClient() throws Exception {
        T existClient = clientQueue.poll();
        if (existClient != null) {
            return existClient;
        }

        if (clientList.size() < CAPACITY) {
            synchronized (clientList) {
                if (clientList.size() < CAPACITY) {
                    // TODO 读取配置,设置特定的T
                    T newClient = createClient();
                    clientList.add(newClient);
                    clientQueue.add(newClient);
                    LOG.info("已加入客户端个数={}", clientList.size());
                }
            }
        }
        return clientQueue.take();
    }


    public void returnToPool(T client) {
        if (client == null) {
            LOG.error("要返还的客户端为空,直接退出!");
        }
        checkRunning();
        clientQueue.add(client);
    }

    protected void checkRunning() {
        if (!runState.compareAndSet(EmRunState.RUNNING.getValue(), EmRunState.RUNNING.getValue())) {
            throw new RuntimeException("已经关闭!");
        }
    }

    public void closeAll() {
        for (T client : clientList) {
            LOG.info("Quit client" + client);
            closeOne(client);
            client = null;
        }
    }

}
